home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1999-10-12 | 8.6 KB | 316 lines | [ TEXT/CWIE]
/* File: SamplePlugin.cp Contains: Interface between NSL Manager and an extremely simple plugin. Written by: Kevin Arnold Copyright: ©1998 - 1999 by Apple Computer, Inc., all rights reserved. Change History (most recent first): <13> 07/07/99 sns no longer use MemMgr.h; cleanup <12> 06/14/99 KA no longer use NSLUtility.h <11> 05/18/99 KA fixed small mem leak <10> 04/29/99 KA make local copies of search data <09> 04/14/99 KA converting to UPP callbacks to manager <08> 03/24/99 KA converting to new headers <07> 03/22/99 KA converting to new data type names (ie NSLXXX) <06> 03/11/99 KA oops, we weren't closing our resource fork after doing a lookup <05> 02/23/99 KA took out call to GetPluginInfo as that is no longer called in 1.1 (NSLI resource) <04> 01/12/99 KA using new parsing calls <03> 12/16/98 KA added code to use the NSL PluginResource Info stuff <02> 11/02/98 KA added some more neighborhoodlookup code and fixed the plugin info stuff <01> 10/12/98 KA initial checkin <00> 10/09/98 KA created */ #include <stdlib.h> #include <string.h> #include <Threads.h> #include "NSL.h" #include "NSLPluginModule.h" static Boolean gsPluginInitialized = false; static NSLPluginDataPtr gPluginInfoPtr = NULL; #define kDefaultNeighborhood "Test Neighborhood" #define kTestURLStringsID 128 // shared lib init routine extern "C" OSStatus __initialize( CFragInitBlockPtr initBlock ); // our library init routine extern "C" OSStatus Initialize( CFragInitBlockPtr initBlock ); // internal prototype OSStatus DoLookupOnService( char* service, NSLNeighborhood neighborhood, NSLMgrNotifyUPP notifier, NSLPluginAsyncInfoPtr pluginInfo ); /******** * Init * ******** The library init routine that gets called when this library is loaded. Its primary function is to grab and remember the FSSpec so we can find our resource fork later. */ static FSSpec sSLPLibSpec; static FSSpec* sLibSpecPtr = NULL; OSStatus Initialize( CFragInitBlockPtr initBlock ) { OSStatus initStatus=noErr; initStatus = __initialize( initBlock ); // the CW init routine - we must call!!! // KA 7/15/98 if ( !initStatus && !sLibSpecPtr ) // only call us once { sLibSpecPtr = &sSLPLibSpec; sSLPLibSpec = *(initBlock->fragLocator.u.onDisk.fileSpec); gsPluginInitialized = true; } return initStatus; } #pragma export on OSStatus InitPlugin( void ) { OSStatus status = noErr; // do any intialization code here. This will be called once per instance return status; } OSStatus KillPlugin( Boolean forceQuit ) { OSStatus status = noErr; // do any clean up here as this instance of the plugin will be unloaded shortly return status; } OSStatus Register( NSLTypedDataPtr dataPtr ) { OSStatus status = noErr; return status; } OSStatus Deregister( NSLTypedDataPtr dataPtr ) { return noErr; } OSStatus StartNeighborhoodLookup( NSLNeighborhood neighborhood, NSLMgrNotifyUPP notifier, NSLPluginAsyncInfoPtr pluginInfo ) { OSStatus status = noErr; char* nPtr = NULL; long nLength; if ( neighborhood && notifier && pluginInfo ) { // we want to do our lookup here. This can be a seperately created thread or have // some async behavior with our own async callback routines. For this example we // are just performing sync. // for the sample we will just notify the manager with a bogus Neighborhood // if the neighborhood name is empty. If not, then just append a dash and a number NSLGetNameFromNeighborhood( neighborhood, &nPtr, &nLength ); if ( nPtr && *nPtr == '\0' ) { pluginInfo->searchState = kNSLSearchStateOnGoing; pluginInfo->searchResult = status; pluginInfo->resultBuffer = kDefaultNeighborhood; pluginInfo->bufferLen = strlen( pluginInfo->resultBuffer )+1; InvokeNSLMgrNotifyUPP( pluginInfo, notifier ); } else if ( nPtr == NULL ) { status = memFullErr; } else { char* tempBuf = ::NewPtr( nLength + 2 ); pluginInfo->searchState = kNSLSearchStateOnGoing; pluginInfo->searchResult = status; pluginInfo->resultBuffer = tempBuf; ::strcpy( pluginInfo->resultBuffer, nPtr ); ::strcat( pluginInfo->resultBuffer, "-1" ); pluginInfo->bufferLen = nLength + 2; InvokeNSLMgrNotifyUPP( pluginInfo, notifier ); pluginInfo->searchState = kNSLSearchStateOnGoing; pluginInfo->searchResult = status; pluginInfo->resultBuffer = tempBuf; ::strcpy( pluginInfo->resultBuffer, nPtr ); ::strcat( pluginInfo->resultBuffer, "-2" ); pluginInfo->bufferLen = nLength + 2; InvokeNSLMgrNotifyUPP( pluginInfo, notifier ); ::DisposePtr( tempBuf ); } pluginInfo->searchState = kNSLSearchStateComplete; pluginInfo->searchResult = status; pluginInfo->resultBuffer = NULL; pluginInfo->bufferLen = 0; InvokeNSLMgrNotifyUPP( pluginInfo, notifier ); if ( nPtr ) ::DisposePtr( nPtr ); } else status = kNSLErrNullPtrError; return status; } OSStatus StartServicesLookup( NSLNeighborhood neighborhood, NSLTypedDataPtr dataPtr, NSLMgrNotifyUPP notifier, NSLPluginAsyncInfoPtr pluginInfo ) { OSStatus status = noErr; char service[256]; char* serviceListPtr; char* localServiceListCopy; NSLNeighborhood localNeighborhoodCopy; UInt16 listLen; char* curPtr; if ( neighborhood && dataPtr && notifier && pluginInfo ) { status = NSLParseServicesRequestPB( dataPtr, &serviceListPtr, &listLen); localNeighborhoodCopy = NSLCopyNeighborhood( neighborhood ); localServiceListCopy = ::NewPtr( listLen ); ::BlockMove( serviceListPtr, localServiceListCopy, listLen ); // can't guarantee that dataPtr data will still be around after notification to the manager curPtr = localServiceListCopy; UInt32 numSvcs = ( (NSLServicesListHeaderPtr) serviceListPtr)->numServices; curPtr += sizeof(NSLServicesListHeader) ; // we are now pointing at the first services which is a pascal style string for ( UInt32 i=1; i <= numSvcs && status == noErr; i++ ) { memcpy( service, curPtr, curPtr[0]+1 ); p2cstr( (unsigned char*)service ); // convert to cstring status = DoLookupOnService( service, localNeighborhoodCopy, notifier, pluginInfo ); // this will handle a search curPtr += curPtr[0]+1; // advance to the next service } // since we are handling these lookups in a sync fashion, we know that we are done when we get here... pluginInfo->searchState = kNSLSearchStateComplete; pluginInfo->searchResult = status; pluginInfo->resultBuffer = NULL; pluginInfo->bufferLen = 0; InvokeNSLMgrNotifyUPP( pluginInfo, notifier ); ::DisposePtr( localServiceListCopy ); NSLFreeNeighborhood( localNeighborhoodCopy ); } else status = kNSLErrNullPtrError; return status; } OSStatus ContinueLookup( NSLMgrNotifyUPP notifier, NSLPluginAsyncInfoPtr pluginInfo ) { OSStatus status = noErr; return status; } OSStatus CancelLookup( NSLPluginAsyncInfoPtr pluginInfo ) { OSStatus status = noErr; return status; } OSStatus ErrNumToString( OSStatus theErr, char* errorString, char* solutionString ) { OSStatus status = noErr; return status; } #pragma export off OSStatus DoLookupOnService( char* service, NSLNeighborhood neighborhood, NSLMgrNotifyUPP notifier, NSLPluginAsyncInfoPtr pluginInfo ) { OSStatus status = noErr; char* nPtr = NULL; long nLength; NSLGetNameFromNeighborhood( neighborhood, &nPtr, &nLength ); if ( !status && nPtr && strcmp( nPtr, kDefaultNeighborhood ) == 0 ) { Str255 url; short pluginRefNum, index = 1; Boolean done = false; // we are going to get our results from a resource for easy testing pluginRefNum = ::FSpOpenResFile( sLibSpecPtr, fsCurPerm ); if ( pluginRefNum != -1 ) { while ( !done ) { YieldToAnyThread(); // in case we are in a multithread aware situation SystemTask(); // be friendly to other tasks... ::GetIndString( url, kTestURLStringsID, index++ ); if ( url[0] > 0 ) { p2cstr( url ); // convert to c-style string long serviceLenOfURL = strstr( (char*)url, ":/" ) - (char*)url; long serviceLenOfService = strlen(service); if ( memcmp( service, url, serviceLenOfService ) == 0 && ( serviceLenOfURL == serviceLenOfService )) { pluginInfo->searchState = kNSLSearchStateOnGoing; pluginInfo->searchResult = status; pluginInfo->resultBuffer = (char*)url; pluginInfo->bufferLen = strlen( pluginInfo->resultBuffer )+1; InvokeNSLMgrNotifyUPP( pluginInfo, notifier ); } } else done = true; } ::CloseResFile( pluginRefNum ); } else status = resNotFound; } else if ( nPtr == NULL ) { status = memFullErr; } if ( nPtr ) ::DisposePtr( nPtr ); return status; }